package com.free.semantic.core.proxy.impl;

import com.free.semantic.common.BaseNode;
import com.free.semantic.common.Ls;
import com.free.semantic.common.ParamNode;
import com.free.semantic.common.RangeObj;
import com.free.semantic.core.ConceptInstanceManage;
import com.free.semantic.core.ConceptManage;
import com.free.semantic.core.FunctionProvider;
import com.free.semantic.core.RelationFunction;
import com.free.semantic.core.proxy.HttpInstanceProxy;
import com.free.semantic.core.script.SemanticNetEngine;
import com.free.semantic.core.script.impl.ScriptEngineImpl;
import com.free.semantic.core.takeclient.ConceptInsTakeCommand;
import org.apache.commons.collections4.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import static com.free.semantic.common.RangeObj.more;
import static com.free.semantic.common.RangeObj.one;
import static com.free.semantic.core.concept.impl.ConceptSelfInfoConcept.*;
import static com.free.semantic.core.concept.impl.ImplementRegisterConcept.*;

public class ConceptInsManageProxy implements ConceptInstanceManage, HttpInstanceProxy {

    private final ConceptInstanceManage instanceManage;

    private final ConceptInsTakeCommand commandClient;

    public ConceptInsManageProxy(ConceptInsTakeCommand commandClient) {
        this.commandClient = commandClient;
        SemanticNetEngine engine = new ScriptEngineImpl();
        this.instanceManage = engine.buildManageInsFromTake(commandClient);
    }

    @Override
    public ConceptManage concept() {
        return instanceManage.concept();
    }

    @Override
    public void registerFunction(List<String> sourceObj, String destObj, RelationFunction relationFunction) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void registerFunction(List<RangeObj> sourceObj, RangeObj destObj, RelationFunction relationFunction) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void registerFunction(String providerName, FunctionProvider functionProvider) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void registerFunction(String providerName, ConceptInstanceManage functionProvider) {
        throw new UnsupportedOperationException();
    }

    @Override
    public RelationFunction getFunction(List<String> sourceObj, String destObj) {
        if (CollectionUtils.isEmpty(sourceObj) || destObj == null) {
            throw new IllegalArgumentException();
        }
        List<String> hasImplement = commandClient.take(Ls.of(
                        new ParamNode(SOURCE, sourceObj),
                        new ParamNode(DEST, destObj)),
                one(HAS_IMPLEMENT));
        boolean has = Boolean.parseBoolean(hasImplement.get(0));
        if (has) {
            return context -> {
                List<BaseNode> sourceNode = new ArrayList<>();
                for (String s : sourceObj) {
                    sourceNode.add(new ParamNode(s, context.getListValue(s)));
                }
                List<Object> list = commandClient.take(sourceNode, more(destObj));
                context.setValue(destObj, list);
            };
        }
        return null;
    }

    @Override
    public void registerFunction(String functionSourceName, String httpUrl) {
        // todo 此处需要先对相关概念进行探测，查看是否满足注册目标
        commandClient.take(Ls.of(
                new ParamNode(SEMANTIC_IMPLEMENT),
                new ParamNode(FUNCTION_PROVIDER_NAME, functionSourceName),
                new ParamNode(SEMANTIC_IMPLEMENT_URL, httpUrl)), one(FUNCTION_PROVIDER));
    }

    @Override
    public RelationFunction getFunction(List<RangeObj> sourceObj, RangeObj destObj) {
        if (CollectionUtils.isEmpty(sourceObj) || destObj == null) {
            throw new IllegalArgumentException();
        }
        List<String> source = sourceObj.stream().map(obj -> obj.getObjectName()).collect(Collectors.toList());
        List<String> hasImplement = commandClient.take(Ls.of(
                        new ParamNode(SOURCE, source),
                        new ParamNode(DEST, destObj.getObjectName())),
                one(HAS_IMPLEMENT));
        boolean has = Boolean.parseBoolean(hasImplement.get(0));
        if (has) {
            return context -> {
                List<BaseNode> sourceNode = new ArrayList<>();
                for (RangeObj s : sourceObj) {
                    sourceNode.add(new ParamNode(s, context.getListValue(s)));
                }
                List<Object> list = commandClient.take(sourceNode, destObj);
                context.setValue(destObj, list);
            };
        }
        return null;
    }

    @Override
    public List<String> getProviderLs() {
        return commandClient.take(Ls.of(new ParamNode(SEMANTIC_IMPLEMENT)), more(FUNCTION_PROVIDER));
    }

    @Override
    public <T> List<T> takePath(List<ParamNode> from, String destObject) {
        return instanceManage.takePath(from, destObject);
    }

    @Override
    public <T> List<T> takePath(List<ParamNode> from, RangeObj destObject) {
        return instanceManage.takePath(from, destObject);
    }

    @Override
    public <T> List<T> goByLocatorNode(List<BaseNode> sourceObj, RangeObj destObj) {
        return commandClient.take(sourceObj, destObj);
    }

    @Override
    public void hideObject(List<String> objectName) {
        instanceManage.hideObject(objectName);
    }

}
